package com.yunzai.secure.exception;

import com.yunzai.generic.domain.JSONResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.text.SimpleDateFormat;
import java.util.Date;

@RestControllerAdvice
public class SecureException {

    private static final Logger log = LogManager.getLogger(SecureException.class);
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @ExceptionHandler(ServiceException.class)
    public JSONResult handleServiceException(ServiceException e) {
        logError("业务处理异常", e);
        return JSONResult.error(e.getMessage());
    }

    @ExceptionHandler({AccessDeniedException.class, InsufficientAuthenticationException.class})
    public JSONResult handleAuthException(RuntimeException e) {
        logError("权限验证失败", e);
        return JSONResult.error(403, "访问权限不足");
    }

    @ExceptionHandler({BadCredentialsException.class, UsernameNotFoundException.class})
    public JSONResult handleCredentialsException(RuntimeException e) {
        logError("凭证验证失败", e);
        return JSONResult.error(401, "用户名或密码错误");
    }

    @ExceptionHandler({LockedException.class, DisabledException.class})
    public JSONResult handleAccountStatusException(RuntimeException e) {
        logError("账户状态异常", e);
        return JSONResult.error(403, "账户状态异常");
    }

    @ExceptionHandler({AccountExpiredException.class, CredentialsExpiredException.class})
    public JSONResult handleExpiredException(RuntimeException e) {
        logError("凭证已过期", e);
        return JSONResult.error(410, "凭证已过期");
    }

    @ExceptionHandler(InternalAuthenticationServiceException.class)
    public JSONResult handleAuthSystemError(InternalAuthenticationServiceException e) {
        logError("认证系统异常", e);
        return JSONResult.error(500, "认证服务异常，请联系管理员 [" + sdf.format(new Date()) + "]");
    }

    @ExceptionHandler(RuntimeException.class)
    public JSONResult handleUnexpectedError(RuntimeException e) {
        logError("系统异常", e);
        return JSONResult.error(500, "系统异常 [" + sdf.format(new Date()) + "]");
    }

    private void logError(String message, Exception e) {
        log.error("[{}] {}", sdf.format(new Date()), message, e);
    }
}
